
#include "ParameterManager.h"
#include "SpecializedParameters.h"

using namespace System;
using namespace ttg_internal::utils;

//------------------------
//--- ParameterManager ---
//------------------------

ParameterManager::ParameterManager()
{
	_sets = gcnew Dictionary<ttg::math::uint64, ParameterSet ^>();
	_currentSetID = 0;
	_parameters = gcnew Dictionary<ttg::math::uint64, Parameter ^>();
	_currentParameterID = 0;
	_root = gcnew ParameterSet("ttgLib", nullptr);
	_root->Tag = _currentSetID++;
	_sets->Add(_root->Tag, _root);
}

void ParameterManager::removeSet(ParameterSet ^set)
{
	_sets->Remove(set->Tag);
	for each (ParameterSet ^s in set->SubSets)
		removeSet(s);
	for each (Parameter ^p in set->Parameters)
		_parameters->Remove(p->Tag);
	set->SubSets->Clear();
	set->Parameters->Clear();
}

ttg::math::uint64 ParameterManager::createSet(String ^name, ttg::math::uint64 root_set)
{
	lock();
	//Getting owner.
	ParameterSet ^owner;
	if ((owner = findSet(root_set)) == nullptr)
		owner = _root;
	//Creating.
	ParameterSet ^res = gcnew ParameterSet(name, owner);
	owner->addSubSet(res);
	res->Tag = _currentSetID++;
	_sets->Add(res->Tag, res);
	unLock();
	return res->Tag;
}

ParameterSet ^ParameterManager::findSet(ttg::math::uint64 ID)
{
	ParameterSet ^res;
	if (_sets->TryGetValue(ID, res))
		return res;
	else
		return nullptr;
}

void ParameterManager::releaseSet(ttg::math::uint64 ID)
{
	lock();
	ParameterSet ^set;
	if (_sets->TryGetValue(ID, set))
	{
		removeSet(set);
		if (set->Owner != nullptr)
			set->Owner->removeSubSet(set);
	}
	unLock();
}

ttg::math::uint64 ParameterManager::createParameter(String ^name,
													String ^type,
													ttg::math::uint64 root_set)
{
	lock();
	//Getting owner.
	ParameterSet ^owner;
	if ((owner = findSet(root_set)) == nullptr)
		owner = _root;
	//Creating and adding parameter.
	Parameter ^p;
	ParameterType t = ParameterInfo::determineType(type);
	if (t == ParameterType::Bool)
		p = gcnew ParameterBool(name, gcnew ParameterInfo_Bool(type), owner); else
	if (t == ParameterType::Double)
		p = gcnew ParameterDouble(name, gcnew ParameterInfo_Double(type), owner); else
	if (t == ParameterType::Enum)
		p = gcnew ParameterEnum(name, gcnew ParameterInfo_Enum(type), owner); else
	if (t == ParameterType::Int64)
		p = gcnew ParameterInt64(name, gcnew ParameterInfo_Int64(type), owner); else
	if (t == ParameterType::String)
		p = gcnew ParameterString(name, gcnew ParameterInfo_String(type), owner);
	else
		p = gcnew ParameterVoid(name, gcnew ParameterInfo_Void(type), owner);
	owner->addParameter(p);
	p->Tag = _currentParameterID++;
	_parameters->Add(p->Tag, p);
	unLock();
	return p->Tag;
}

Parameter ^ParameterManager::findParameter(ttg::math::uint64 ID)
{
	Parameter ^res;
	if (_parameters->TryGetValue(ID, res))
		return res;
	else
		return nullptr;
}

void ParameterManager::releaseParameter(ttg::math::uint64 ID)
{
	lock();
	Parameter ^p = findParameter(ID);
	if (p != nullptr)
	{
		_parameters->Remove(ID);
		if (p->Owner != nullptr)
			p->Owner->removeParameter(p);
	}
	unLock();
}
